﻿using System;
using System.Web.Caching;
using System.IO;

using Filter = System.Predicate<string>;

namespace System.Web.ScriptBuilder
{
	class DirectoryCacheDependency : CacheDependency
	{
		private FileSystemWatcher m_DirWatcher;
		private string m_uniqueId;
		private Filter m_fileFilter;
		private bool m_includeSubdirectories;

		public DirectoryCacheDependency(string directoryPath)
			: this(directoryPath, false, null)
		{

		}
		public DirectoryCacheDependency(string directoryPath, bool includeSubdirectories)
			: this(directoryPath, includeSubdirectories, null)
		{

		}
		public DirectoryCacheDependency(string directoryPath, bool includeSubdirectories, Filter fileFilter)
		{
			if (directoryPath == null)
				throw new ArgumentNullException("directoryPath");

			var mask = (string)null;
			PathUtils.SplitPathFromMask(ref directoryPath, ref mask);

			this.m_includeSubdirectories = includeSubdirectories;
			this.m_fileFilter = fileFilter;
			this.InitSystemWatcher(directoryPath, mask);
			this.FinishInit();
			this.InitUniqueID(directoryPath + mask);
		}

		protected override void DependencyDispose()
		{
			if (m_DirWatcher != null)
				this.m_DirWatcher.Dispose();
		}

		public override string GetUniqueID()
		{
			return m_uniqueId;
		}

		private void InitUniqueID(string path)
		{
			m_uniqueId = path;
		}
		private void InitSystemWatcher(string directoryPath, string mask)
		{
			this.m_DirWatcher = new FileSystemWatcher(directoryPath, mask);
			this.m_DirWatcher.Created += ((sender, e) =>
			{
				if (m_fileFilter(e.FullPath))
					return;

				if ((e.ChangeType & WatcherChangeTypes.Created) != 0)
					this.NotifyDependencyChanged(sender, e);
			});
			this.m_DirWatcher.IncludeSubdirectories = m_includeSubdirectories;
			this.m_DirWatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
				| NotifyFilters.FileName;
		}
	}
}
